package server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class Repository {

	// to implement hash table
	Map<String, Integer> repository;
	ArrayList<IdOfClient> list = new ArrayList<IdOfClient>();

	public Repository() {
		repository = new HashMap<String, Integer>();
		// temporarily giving values
		initialItems("1111", 23);
		initialItems("2222", 16);
		initialItems("3333", 18);
		initialItems("4444", 3);
	}

	public HashMap<String, Integer> getState(){
		return (HashMap<String, Integer>) repository;
	}
	
	public void upDate(HashMap<String, Integer> s){
		repository = s;
	}
	
	void initialItems(String item, int quantity) {
		repository.put(item, quantity);
	}

	void updateItems(String item, int quantity) {
		synchronized (repository.get(item)){
			repository.put(item, quantity);
		}
	}

	int getQuantity(String key){
		int number = 0;
		if(key!=null) {
			synchronized (repository.get(key)){
				number = repository.get(key);
			}
		}
		return number;
	}

	void addQuantity(String item, int number){
		int present = getQuantity(item);
		updateItems(item, (number+present));
	}

	void subtractQuantity(String item, int number) {
		int present = getQuantity(item);
		updateItems(item, (present-number));
	}

	boolean exchange(String returning, int number, String buying, int quantity){
		boolean result = false;
		synchronized(repository.get(buying)){
			int present;
			present = repository.get(buying);
			if(present>=quantity){
				synchronized(repository.get(returning)){
					repository.put(buying, (present-quantity));// buy
					int temp = repository.get(returning);
					repository.put(returning, (number+temp));// return
					result = true;
				}
			}
		}
		return result;
	}

	synchronized int checkAndBuy(String item, int number) {
		int bought = getQuantity(item);
		if(bought>=number){
			subtractQuantity(item, number);
			return number;
		} else {
			subtractQuantity(item, bought);
			return bought;	
		}
	}

	int hold(String client, String item, int number){
		// create IdOfclient 
		IdOfClient c = new IdOfClient(client);
		list.add(c);
		int holding = checkAndBuy(item, number);
		// if number of item available
		c.hold = number;
		c.itemInHold = item;
		System.out.println("Holding "+holding +" of "+item+" for "+client);
		return holding;
	}

	boolean abort(String id){
		IdOfClient client = getClient(id);
		// remove from list
		if(remove(id)){
			// add to stock
			addQuantity(client.itemInHold, client.hold);
			System.out.println("Rolled back "+client.id+"'s holdings.");			
			return true;
		}else{
			return false;
		}
	}

	boolean remove(String id){
		// remove from list
		for (int i=0;i<list.size();i++){
			if (list.get(i).id.equals(id)){
				list.remove(i); 
				return true;
			}
		}
		return false;
	}

	IdOfClient getClient(String id){
		for (int i=0;i<list.size();i++){
			if (list.get(i).id.equals(id)){
				return list.get(i);
			} 
		}
		return null;
	}
	
	class IdOfClient{
		String id;
		int hold;
		String itemInHold;
		
		public IdOfClient(String name) {
			id = name;
		}
	}
}
